package com.cdc.http.http2;



import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.zip.GZIPInputStream;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;

/**
 * Created by admin on 2018/3/24.
 */

public class RequestTask<T> implements Runnable {

    private Request<T> request;
    private HttpListener<T> httpListener;

    public RequestTask(Request request, HttpListener<T> httpListener) {
        this.request = request;
        this.httpListener=httpListener;
    }

    @Override
    public void run() {

        Exception exception=null;
        int responseCode=-1;
        Map<String,List<String>> responseHeaders=null;
    byte[] responseBody=null;
        String urlStr=request.getUrl();
        RequestMethod method=request.getMethod();
        HttpURLConnection urlConnection=null;
        OutputStream outputStream=null;
        try {
            URL url=new URL(urlStr);
            //
            //urlConnection= (HttpURLConnection) url.openConnection();
            //一句话切换OKHttp与HttpURLConnection
            urlConnection= (HttpURLConnection) url.openConnection();
            if(urlConnection instanceof HttpsURLConnection){
                HttpsURLConnection httpsURLConnection= (HttpsURLConnection) urlConnection;
                SSLSocketFactory sslSocketFactory=request.getmSSLSocketFactory();
                if(sslSocketFactory!=null){
                    httpsURLConnection.setSSLSocketFactory(sslSocketFactory);//https证书相关信息
                }
                HostnameVerifier hostnameVerifier=request.getmHostnameVerifier();
                if(hostnameVerifier!=null){
                    httpsURLConnection.setHostnameVerifier(hostnameVerifier);//服务器主机认证
                }
            }

            urlConnection.setRequestMethod(method.getValue());
            urlConnection.setDoInput(true);
            urlConnection.setDoOutput(method.isOutputMethod());
            setHeader(urlConnection,request);
            //2.发送数据
             if(method.isOutputMethod()){
                 outputStream=urlConnection.getOutputStream();
                 request.onWriteBopdy(outputStream);
             }

             //3.读取响应
           responseCode=urlConnection.getResponseCode();
            responseHeaders=urlConnection.getHeaderFields();
            if(hasResponseBody(method,responseCode)){
               InputStream inputStream= getInputStream(urlConnection,responseCode);
                ByteArrayOutputStream arrayOutputStream=new ByteArrayOutputStream();
                int len;
                byte[] buffer=new byte[2048];
                while((len=inputStream.read(buffer))!=-1){
                    arrayOutputStream.write(buffer,0,len);
                }
                arrayOutputStream.close();
                responseBody=arrayOutputStream.toByteArray();
            }
        } catch (IOException e) {
            exception=e;
        }finally {
            if(urlConnection!=null){
                urlConnection.disconnect();
            }
        }
        //4.解析服务器的数据
        T t=request.parseResponse(responseBody);
        Response<T> response=new Response<T>(responseCode,responseHeaders,exception,request);
        response.setResult(t);

        Message message=new Message(response,httpListener);
        Poster.getInstance().post(message);
    }

    /**
     * 判断是否有响应包体
     * @param requestMethod
     * @param responseCode
     * @return
     */
    private boolean hasResponseBody(RequestMethod requestMethod, int responseCode){
        return requestMethod!= RequestMethod.HEAD  //head没有请求包体
                && !(100<=responseCode && responseCode<200) //不在[100,200)
                && responseCode !=204 && responseCode !=205 //不是20和205
                && !(300 <= responseCode && responseCode <400); //不在[300,400)
        
    }

    /**
     * 根据响应码获得服务器的流
     * @param urlConnection
     * @param responseCode
     * @return
     */
    private InputStream getInputStream(HttpURLConnection urlConnection, int responseCode) throws IOException {
        InputStream inputStream=null;
        if(responseCode>=400){
            inputStream=urlConnection.getErrorStream();
        }else{
            inputStream=urlConnection.getInputStream();
        }
        String contentcoding=urlConnection.getContentEncoding();
        //判断流是否被压缩了
        if(contentcoding!=null && contentcoding.contains("gzip")){
            inputStream=new GZIPInputStream(inputStream);
        }
        return inputStream;
    }

    public void setHeader(HttpURLConnection httpURLConnection,Request request){
        Map<String,String> requestHead=request.getmRequestHeads();
        //处理ContentType
        String contentType=request.getmContentType();
        requestHead.put("Content-Type",contentType);

        //处理ContentLength
        long contentLength=request.getContentLength();
        requestHead.put("Content-Length",Long.toString(contentLength));

        for (Map.Entry<String, String> stringStringEntry : requestHead.entrySet()) {
            String headKey=stringStringEntry.getKey();
            String headValue=stringStringEntry.getValue();
            httpURLConnection.setRequestProperty(headKey,headValue);

        }

    }
}
